package com.rickie.executor;

import com.alibaba.cola.dto.SingleResponse;
import com.alibaba.cola.exception.BizException;
import com.alibaba.cola.extension.ExtensionExecutor;
import com.rickie.extension.IBookingPreValidateExtPt;
import com.rickie.gateway.CargoBookingGateway;
import com.rickie.model.aggregates.Cargo;
import com.rickie.dto.command.CargoBookCmd;
import com.rickie.dto.data.ErrorCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.UUID;

/**
 * @author rickie
 * @version 1.0.0
 * @ClassName CargoBookingCmdExe.java
 * @Description 预定货物命令处理程序
 * @createTime 2021年06月14日 12:17:00
 */
@Component
public class CargoBookingCmdExe {
    @Resource
    private ExtensionExecutor extensionExecutor;

    @Resource
    private CargoBookingGateway cargoBookingGateway;

    public SingleResponse<String> execute(CargoBookCmd cmd) {
        //The flow of usecase is defined here.
        //The core ablility should be implemented in Domain. or sink to Domain gradually
        // 验证入参
        if(cmd.getOriginLocation().isEmpty() || cmd.getOriginLocation().equals("") ||
                cmd.getDestLocation().isEmpty() || cmd.getDestLocation().equals("")){
            throw new BizException(ErrorCode.LOCATION_EMPTY.getErrCode(), "位置为空");
        }
        if(cmd.getBookingAmount()<0) {
            throw new BizException(ErrorCode.BOOKING_AMOUNT_NEGATIVE.getErrCode(), "预订数量不能为负数");
        }

        // 扩展点-检查预定编号是否重复，预定货物是否存在
        boolean validate = extensionExecutor.execute(IBookingPreValidateExtPt.class, cmd.getBizScenario(), extension -> extension.validate(cmd));
        if(!validate){
            throw new BizException(ErrorCode.BOOKING_AMOUNT_NEGATIVE.getErrCode(), "请重新下单");
        }

        // 调用仓储能力
        String random = UUID.randomUUID().toString().toUpperCase();
        cmd.setBookingId(random.substring(0, random.indexOf("-")));
        Cargo cargo = new Cargo(cmd);
        cargoBookingGateway.save(cargo);

        SingleResponse<String> singleResponse = SingleResponse.buildSuccess();
        singleResponse.setData(cmd.getBookingId());
        return singleResponse;
    }
}
